﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;

namespace MetroDataApi.Models
{
    public class Recent2Changes
    {
        public static List<recentChanges> AllChanges(int prjId, string startTime, string endTime)
        {
            try
            {
                using (var db = new MetroDataDataContext())
                {
                    var list = new List<recentChanges>();
                    var monitorLocations = from p in db.MonitorPointsDictionary
                                           where p.PrjId == prjId
                                           group p by new { p.Location, p.MonitorType } into g
                                           select g.Key;
                    foreach (var k in monitorLocations)
                    {
                        var changes = Recent2Changes.GetChanges(prjId, k.MonitorType, k.Location, startTime, endTime, "1");
                        if (changes.curValues.Count() > 0)
                        {
                            list.Add(changes);
                        }
                    }
                    return list;
                }
            }
            catch
            {
                return new List<recentChanges>();
            }
        }

        /// <summary>
        /// time1,time2的顺序无所谓,自动调整
        /// </summary>
        /// <param name="prjId"></param>
        /// <param name="type"></param>
        /// <param name="location"></param>
        /// <param name="time1"></param>
        /// <param name="time2"></param>
        /// <param name="fuzzy"></param>
        /// <returns></returns>
        public static recentChanges GetChanges(int prjId, string type, string location,
            string time1 = "", string time2 = "", string fuzzy = "0", bool isDesign = false)
        {
            try
            {
                var locationPts = ProjectsHelper.GetLocationPointsByType(prjId, type).Where(p => p.location == location).SingleOrDefault();
                var names = locationPts.points.Select(p => p.name).ToList();
                var recentAllTimes = new List<string>();
                var times = new List<string>();
                if (time1.Length == 0)
                {
                    times = Recent2Changes.GetRecent2Times(prjId, names, out recentAllTimes);
                }
                else
                {
                    times.Add(time1);
                    times.Add(time2);
                    //如果time1,time2是降序排列,下面的代码中,计算时要求*顺序*排列
                    if (DateTime.Parse(time1) > DateTime.Parse(time2))
                    {
                        times.Reverse();
                    }

                    if (fuzzy == "1")//模糊日期查询,用户只指定了前后时间段,需要查找具体测项日期
                    {
                        //根据起始时间,寻找最符合的最大和最小日期
                        times = Recent2Changes.GetActual2TimesByFuzzyTime(prjId, names, times);
                    }
                }
                var oTime = QueryResults.GetOriginTime(prjId, names[0]);
                if (names.Count == 0 || times.Count < 2 || oTime == "")
                {
                    return new recentChanges();
                }

                var originValues = isDesign ? null : QueryResults.GetOriginResults(prjId, names);
                //测量的值
                var lastValues = QueryResults.GetResultsByTime(prjId, times[0], names);
                var currentValues = QueryResults.GetResultsByTime(prjId, times[1], names);
                //计算后的值
                var lastCaculatedValues = QueryResults.GetDiffBy2ResultsList(originValues, lastValues, isDesign).ToList();
                var currentCaculatedValues = QueryResults.GetDiffBy2ResultsList(originValues, currentValues, isDesign).ToList();
                //对时间的一个特别处理,如果日期一致,那么就具体到时分
                var lastDate = DateTime.Parse(times[0]);
                var curDate = DateTime.Parse(times[1]);
                var lastTimeStr = ""; var curTimeStr = "";
                if (lastDate.Date == curDate.Date)
                {//日期一致
                    lastTimeStr = lastDate.ToString("yyyy-MM-dd HH:mm");
                    curTimeStr = curDate.ToString("yyyy-MM-dd HH:mm");
                }
                else
                {
                    lastTimeStr = lastDate.ToString("yyyy-MM-dd");
                    curTimeStr = curDate.ToString("yyyy-MM-dd");
                }
                var change = new recentChanges()
                {
                    lastValues = lastCaculatedValues,
                    lastTime = lastTimeStr,
                    curValues = currentCaculatedValues,
                    curTime = curTimeStr,
                    max = Math.Max(lastCaculatedValues.Where(p => !double.IsNaN(p.value)).Max(p => p.value),
                        currentCaculatedValues.Where(p => !double.IsNaN(p.value)).Max(p => p.value)),
                    min = Math.Min(lastCaculatedValues.Where(p => !double.IsNaN(p.value)).Min(p => p.value),
                        currentCaculatedValues.Where(p => !double.IsNaN(p.value)).Min(p => p.value)),
                    allTimes = recentAllTimes,
                    originTime = oTime,
                    pointsCount = names.Count,
                    title = location + type
                };
                change.clear();
                //统计最大最小值
                change.summary();
                return change;

            }
            catch
            {
                return new recentChanges();
            }

        }


        public static recentChanges GetReviewedRecentChanges(int prjId, string location, string monitorType, DateTime date)
        {
            using (var db = new MetroDataDataContext())
            {
                var names = db.MonitorPointsDictionary.Where(p => p.PrjId == prjId && p.Location == location && p.MonitorType == monitorType).Select(p => p.Name).ToList();
                var recentAllTimeList = new List<string>();
                var recent2TimesInMonitorPoints = Recent2Changes.GetRecent2Times(prjId, names, out recentAllTimeList);
                IEnumerable<result> lastValues;
                IEnumerable<result> reviewValues;
                IEnumerable<result> originValues;
                string lastTimeStr;
                originValues = QueryResults.GetOriginResults(prjId, names);
                reviewValues = QueryResults.GetReviewResultsByTime(prjId, date.ToString("yyyy-MM-dd"), names);

                if (recent2TimesInMonitorPoints.Count == 0)
                {
                    lastValues = reviewValues;
                    lastTimeStr = date.ToString("yyyy-MM-dd");
                }
                else
                {

                    lastTimeStr = recent2TimesInMonitorPoints[1];
                    lastValues = QueryResults.GetResultsByTime(prjId, lastTimeStr, names);
                }
                var lastChanges = QueryResults.GetDiffBy2ResultsList(originValues, lastValues);
                var reviewChanges = QueryResults.GetDiffBy2ResultsList(originValues, reviewValues);

                var change = new recentChanges()
                {
                    lastValues = lastChanges,
                    lastTime = DateTime.Parse(lastTimeStr).ToString("yyyy-MM-dd"),
                    curValues = reviewChanges,
                    curTime = date.ToString("yyyy-MM-dd"),
                    max = Math.Max(lastChanges.Where(p => !double.IsNaN(p.value)).Max(p => p.value),
                        reviewChanges.Where(p => !double.IsNaN(p.value)).Max(p => p.value)),
                    min = Math.Min(lastChanges.Where(p => !double.IsNaN(p.value)).Min(p => p.value),
                        reviewChanges.Where(p => !double.IsNaN(p.value)).Min(p => p.value)),
                    pointsCount = names.Count,
                    title = location + monitorType,
                    originTime = QueryResults.GetOriginTime(prjId, names[0])
                };
                change.clear();
                //统计最大最小值
                change.summary();
                return change;



            }
        }


        public static List<string> get2Times(int prjId, string location, string monitorType, string startTime, string endTime)
        {
            var times = new List<string>();

            using (var db = new MetroDataDataContext())
            {
                var names = db.MonitorPointsDictionary.Where(p => p.PrjId == prjId && p.Location == location && p.MonitorType == monitorType).Select(p => p.Name).ToList();
                times.Add(startTime); times.Add(endTime);
                if (startTime == "" && endTime == "")
                {
                    var ss = new List<string>();
                    times = Recent2Changes.GetRecent2Times(prjId, names, out ss);
                }
                else if (endTime != "" && startTime == "")
                {
                    times = Recent2Changes.Get2TimesByLastTime(prjId, endTime, names);
                }
                else if (endTime == "" && startTime != "")
                {
                    times[1] = DateTime.Now.Date.ToString("yyyy-MM-dd");
                    times = Recent2Changes.GetActual2TimesByFuzzyTime(prjId, names, times);
                }
                else
                {
                    times = Recent2Changes.GetActual2TimesByFuzzyTime(prjId, names, times);
                }
                return times;
            }
        }

        public static List<string> Get2TimesByLastTime(int prjId, string lastTime, List<string> names)
        {
            var time = DateTime.Parse(lastTime);
            using (var db = new MetroDataDataContext())
            {
                var ptname = names[0];
                var t = (from p in db.MonitorPoints
                         where p.PrjId == prjId && p.Name == ptname && p.DateTime <= time
                         orderby p.DateTime descending
                         select p.DateTime.Value).Take(2).ToList();
                if (t.Count == 1)
                {
                    t.Add(t[0]);
                }
                return t.Select(p => p.ToString("yyyy-MM-dd")).ToList();
            }
        }

        public static List<string> GetActual2TimesByFuzzyTime(int prjId, List<string> names, List<string> timelist)
        {
            var times = new List<string>();
            var dateList = (from t in timelist select Convert.ToDateTime(t)).OrderBy(t => t).ToList();
            var time1 = dateList[0];
            var time2 = dateList[1];
            using (var db = new MetroDataDataContext())
            {
                if (names.Count == 0) return times;
                var ptname = names[0];
                var timesAll = (from p in db.MonitorPoints
                                where p.PrjId == prjId && p.Name == ptname
                                orderby p.DateTime ascending
                                where p.DateTime.Value >= time1 && p.DateTime.Value <= time2
                                select p.DateTime.Value).ToList();
                var minTime = timesAll.FirstOrDefault();
                var maxTime = timesAll.LastOrDefault();
                if (minTime == null || maxTime == null)
                {
                    //do nothing
                }
                else
                {
                    times.Add(minTime.ToString("yyyy-MM-dd HH:mm:ss"));
                    times.Add(maxTime.ToString("yyyy-MM-dd HH:mm:ss"));
                }
                return times;
            }
        }

        /// <summary>
        /// 获取审核列表中的倒序时间
        /// </summary>
        /// <param name="prjId"></param>
        /// <param name="names"></param>
        /// <returns></returns>
        public static List<string> GetRecentReviewedTimeList(int prjId, List<string> names)
        {
            using (var db = new MetroDataDataContext())
            {
                var list = (from p in db.PreReviewMonitorPoints
                            where p.PrjId == prjId && names.Contains(p.Name)
                            group p.DateTime by p.DateTime.Value into g
                            orderby g.Key descending
                            select g.Key).ToList().Select(p => p.ToString("yyyy-MM-dd HH:mm:ss")).ToList();
                return list;

            }
        }


        /// <summary>
        /// 针对给出的一系列点,寻找该点组的最近2次观测时间
        /// </summary>
        /// <param name="prjId"></param>
        /// <param name="names"></param>
        /// <param name="recentAllTimes"></param>
        /// <returns></returns>
        public static List<string> GetRecent2Times(int prjId, List<string> names, out List<string> recentAllTimes)
        {
            recentAllTimes = new List<string>();
            try
            {
                using (var db = new MetroDataDataContext())
                {
                    if (names.Count == 0) return recentAllTimes;

                    var timesAll = (from p in db.MonitorPoints
                                    where p.PrjId == prjId && names.Contains(p.Name)
                                    group p by p.DateTime.Value into g
                                    orderby g.Key descending
                                    select g.Key).ToList();


                    var times = timesAll.Take(2).ToList();
                    times.Reverse();
                    recentAllTimes = timesAll.Select(p => p.ToString("yyyy-MM-dd")).ToList();
                    if (times.Count == 1)
                    {
                        times.Add(times[0]);
                    }
                    else if (times.Count == 0)
                    {
                        return new List<string>();
                    }
                    return times.Select(p => p.ToString()).ToList();
                }
            }
            catch
            {
                return new List<string>();
            }
        }

    }


}